package org.xjb.cordova.baidulocation;

import java.util.HashMap;
import java.util.Map;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;

public class BaiduLocation extends CordovaPlugin {

	private static final String STOP_ACTION = "stop";
	private static final String GET_ACTION = "getCurrentPosition";
	private boolean enableHighAccuracy;
	private String coorType;
	private int timeout;
	private int scanSpan;
	private boolean isNeedAddress;
	
	public LocationClient locationClient = null;
	public CallbackContext callbackContext = null;
	public BDLocationListener myListener = new MyLocationListener();

	private static final Map<Integer, String> ERROR_MESSAGE_MAP = new HashMap<Integer, String>();

	private static final String DEFAULT_ERROR_MESSAGE = "服务端定位失败";

	static {
		ERROR_MESSAGE_MAP.put(61, "GPS定位结果，GPS定位成功。");
		ERROR_MESSAGE_MAP.put(62, "无法获取有效定位依据，定位失败，请检查运营商网络或者wifi网络是否正常开启，尝试重新请求定位。");
		ERROR_MESSAGE_MAP.put(63, "网络异常，没有成功向服务器发起请求，请确认当前测试手机网络是否通畅，尝试重新请求定位。");
		ERROR_MESSAGE_MAP.put(65, "定位缓存的结果。");
		ERROR_MESSAGE_MAP.put(66, "离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果。");
		ERROR_MESSAGE_MAP.put(67, "离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果。");
		ERROR_MESSAGE_MAP.put(68, "网络连接失败时，查找本地离线定位时对应的返回结果。");
		ERROR_MESSAGE_MAP.put(161, "网络定位结果，网络定位定位成功。");
		ERROR_MESSAGE_MAP.put(162, "请求串密文解析失败。");
		ERROR_MESSAGE_MAP.put(167, "服务端定位失败，请您检查是否禁用获取位置信息权限，尝试重新请求定位。");
	};

	public String getErrorMessage(int locationType) {
		String result = ERROR_MESSAGE_MAP.get(locationType);
		if (result == null) {
			result = DEFAULT_ERROR_MESSAGE;
		}
		return result;
	}

	@Override
	public boolean execute(String action, JSONArray args, final CallbackContext callbackContext)  throws JSONException{
		this.callbackContext = callbackContext;
		if (GET_ACTION.equals(action)) {
			this.enableHighAccuracy = args.getBoolean(0);
			this.coorType = args.getString(1);
			this.timeout = args.getInt(2);
			this.scanSpan = args.getInt(3);
			this.isNeedAddress = args.getBoolean(4);
					
			cordova.getActivity().runOnUiThread(new Runnable() {
				@Override
				public void run() {
					if (locationClient != null && locationClient.isStarted()) {
						locationClient.stop();
					}
					locationClient = new LocationClient(cordova.getActivity());
					locationClient.registerLocationListener(myListener);
					LocationClientOption option = new LocationClientOption();
					
					option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving); // 设置定位模式
					if(enableHighAccuracy) {
						option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy); // 设置定位模式
					}
					option.setCoorType(coorType); // 返回的定位结果是百度经纬度，默认值gcj02
					option.setTimeOut(timeout); // 超时时间
					option.setScanSpan(scanSpan); // 发起定位请求的间隔时间
					option.setIsNeedAddress(isNeedAddress); //是否获取地址
					option.setProdName("BaiduLoc");
					locationClient.setLocOption(option);

					locationClient.start();
					locationClient.requestLocation();
				}

			});
			return true;
		} else if (STOP_ACTION.equals(action)) {
			locationClient.stop();
			callbackContext.success(200);
			return true;
		} else {
			callbackContext.error(PluginResult.Status.INVALID_ACTION.toString());
		}

		return false;
	}

	public class MyLocationListener implements BDLocationListener {
		@Override
		public void onReceiveLocation(BDLocation location) {
			if (location == null)
				return;

			try {
				JSONObject jsonObj = new JSONObject();
				JSONObject coords = new JSONObject();
				coords.put("latitude", location.getLatitude());
				coords.put("longitude", location.getLongitude());
				coords.put("radius", location.getRadius());

				jsonObj.put("coords", coords);

				int locationType = location.getLocType();

				jsonObj.put("locationType", locationType);
				jsonObj.put("code", locationType);
				jsonObj.put("message", getErrorMessage(locationType));

				switch (locationType) {
				case BDLocation.TypeGpsLocation:
					coords.put("speed", location.getSpeed());
					coords.put("altitude", location.getAltitude());
					jsonObj.put("SatelliteNumber", location.getSatelliteNumber());
					break;

				case BDLocation.TypeNetWorkLocation:
					jsonObj.put("addr", location.getAddrStr());
					break;
				}

				callbackContext.success(jsonObj);
			} catch (JSONException e) {
				callbackContext.error(e.getMessage());
			}
		}
	}

	@Override
	public void onDestroy() {
		if (locationClient != null && locationClient.isStarted()) {
			locationClient.stop();
			locationClient = null;
		}
		super.onDestroy();
	}

	public CallbackContext getCallbackContext() {
		return callbackContext;
	}

	public void setCallbackContext(CallbackContext callbackContext) {
		this.callbackContext = callbackContext;
	}
}